Crate calloop[−][src]
Expand description
Calloop, a Callback-based Event Loop
This crate provides an EventLoop
type, which is a small abstraction
over a polling system. The main difference between this crate
and other traditional rust event loops is that it is based on callbacks:
you can register several event sources, each being associated with a callback
closure that will be invoked whenever the associated event source generates
events.
The main target use of this event loop is thus for apps that expect to spend most of their time waiting for events and wishes to do so in a cheap and convenient way. It is not meant for large scale high performance IO.
How to use it
For simple uses, you can just add event sources with callbacks to the event loop. For example, here’s a runnable program that exits after five seconds:
use calloop::{timer::Timer, EventLoop, LoopSignal};
fn main() {
// Create the event loop. The loop is parameterised by the kind of shared
// data you want the callbacks to use. In this case, we want to be able to
// stop the loop when the timer fires, so we provide the loop with a
// LoopSignal, which has the ability to stop the loop from within events. We
// just annotate the type here; the actual data is provided later in the
// run() call.
let mut event_loop: EventLoop<LoopSignal> =
EventLoop::try_new().expect("Failed to initialize the event loop!");
// Retrieve a handle. It is used to insert new sources into the event loop
// It can be cloned, allowing you to insert sources from within source
// callbacks.
let handle = event_loop.handle();
// Create our event source, a timer. Note that this is also parameterised by
// the data for the events it generates. We've let Rust infer that here.
let source = Timer::new().expect("Failed to create timer event source!");
// Most event source APIs provide two things: an event source to go into the
// event loop, and some way of triggering that source from elsewhere. In
// this case, we use a handle to the timer to set timeouts.
//
// Note that this can go before or after the call to insert_source(), and
// even inside another event callback.
let timer_handle = source.handle();
timer_handle.add_timeout(std::time::Duration::from_secs(5), "Timeout reached!");
// Inserting an event source takes this general form. It can also be done
// from within the callback of another event source.
handle
.insert_source(
// a type which implements the EventSource trait
source,
// a callback that is invoked whenever this source generates an event
|event, _metadata, shared_data| {
// This callback is given 3 values:
// - the event generated by the source (in our case, a string slice)
// - &mut access to some metadata, specific to the event source (in our case, a
// timer handle)
// - &mut access to the global shared data that was passed to EventLoop::run or
// EventLoop::dispatch (in our case, a LoopSignal object to stop the loop)
//
// The return type is just () because nothing uses it. Some
// sources will expect a Result of some kind instead.
println!("Event fired: {}", event);
shared_data.stop();
},
)
.expect("Failed to insert event source!");
// Create the shared data for our loop.
let mut shared_data = event_loop.get_signal();
// Actually run the event loop. This will dispatch received events to their
// callbacks, waiting at most 20ms for new events between each invocation of
// the provided callback (pass None for the timeout argument if you want to
// wait indefinitely between events).
//
// This is where we pass the *value* of the shared data, as a mutable
// reference that will be forwarded to all your callbacks, allowing them to
// share some state
event_loop
.run(
std::time::Duration::from_millis(20),
&mut shared_data,
|_shared_data| {
// Finally, this is where you can insert the processing you need
// to do do between each waiting event eg. drawing logic if
// you're doing a GUI app.
},
)
.expect("Error during event loop!");
}
Event source types
The event loop is backed by an OS provided polling selector (epoll on Linux).
This crate also provide some adapters for common event sources such as:
- MPSC channels
- Timers
- unix signals on Linux
As well as generic objects backed by file descriptors.
It is also possible to insert “idle” callbacks. These callbacks represent computations that
need to be done at some point, but are not as urgent as processing the events. These callbacks
are stored and then executed during EventLoop::dispatch
, once all
events from the sources have been processed.
Async/Await compatibility
calloop
can be used with futures, both as an executor and for monitoring Async IO.
Activating the executor
cargo feature will add the futures
module, which provides
a future executor that can be inserted into an EventLoop
as yet another EventSource
.
IO objects can be made Async-aware via the LoopHandle::adapt_io
method. Waking up the futures using these objects is handled by the associated EventLoop
directly.
Custom event sources
You can create custom event sources can will be inserted in the event loop by
implementing the EventSource
trait. This can be done either directly from the file
descriptors of your source of interest, or by wrapping an other event source and further
processing its events. An EventSource
can register more than one file descriptor and
aggregate them.
Platforms support
Currently, only Linux and the *BSD are supported.
Modules
An MPSC channel whose receiving end is an event source
A futures executor as an event source
A generic event source wrapping an IO objects or file descriptor
Adapters for async IO objects
Ping to the event loop
Event source for tracking Unix signals
Timer-based event sources
Structs
An event source with its callback.
An event loop
An idle callback that was inserted in this loop
An error generated when trying to insert an event source
Interest to register regarding the file descriptor
An handle to an event loop
A signal that can be shared between thread to stop or wakeup a running event loop
The polling system
Readiness for a file descriptor notification
A token representing a registration in the EventLoop
.
A token (for implementation of the EventSource
trait)
Factory for creating tokens in your registrations
Enums
Possible modes for registering a file descriptor
Possible actions that can be requested to the event loop by an event source once its events have been processed
Traits
Trait representing an event source